package com.xzzz.irda.guardcat.core.metric.tomcat;


import cn.hutool.core.collection.CollectionUtil;
import com.xzzz.common.base.util.JmxUtil;

import javax.management.ObjectName;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/**
 * Tomcat 信息
 *
 * @author xzzz
 * @since 1.0.0
 */
public class TomcatInfo {


    /**
     * 获取 Tomcat 的监控信息
     *
     * @return List<TomcatServerInfo>
     */
    public static List<TomcatServerInfo> getTomcatServerInfos() {
        Set<ObjectName> servers = JmxUtil.getObjectNameSet(JmxUtil.EMBEDDED_TOMCAT_SERVER);

        if (CollectionUtil.isEmpty(servers)) {
            servers = JmxUtil.getObjectNameSet(JmxUtil.STANDALONE_TOMCAT_SERVER);
            if (CollectionUtil.isEmpty(servers)) {
                return null;
            }
        }

        List<TomcatServerInfo> serverInfoList = new ArrayList<>();
        TomcatServerInfo tomcatServerInfo;

        for (ObjectName server : servers) {
            tomcatServerInfo = new TomcatServerInfo();
            tomcatServerInfo.setServerInfo(JmxUtil.getMbeanStrVal(server, "serverInfo"));
            tomcatServerInfo.setServerNumber(JmxUtil.getMbeanStrVal(server, "serverNumber"));
            tomcatServerInfo.setStateName(JmxUtil.getMbeanStrVal(server, "stateName"));
            tomcatServerInfo.setAddress(JmxUtil.getMbeanStrVal(server, "address"));
            tomcatServerInfo.setPort(JmxUtil.getMbeanIntegerVal(server, "port"));

            serverInfoList.add(tomcatServerInfo);
        }

        return serverInfoList;
    }

    /**
     * 获取 Tomcat 的全局请求处理器的监控信息
     *
     * @return List<TomcatGlobalRequestProcessorInfo>
     */
    public static List<TomcatGlobalRequestProcessorInfo> getTomcatGlobalRequestProcessorInfos() {
        Set<ObjectName> processors = JmxUtil.getObjectNameSet(JmxUtil.EMBEDDED_TOMCAT_GLOBAL_REQUEST_PROCESSOR);
        if (CollectionUtil.isEmpty(processors)) {
            processors = JmxUtil.getObjectNameSet(JmxUtil.STANDALONE_TOMCAT_GLOBAL_REQUEST_PROCESSOR);
            if (CollectionUtil.isEmpty(processors)) {
                return null;
            }
        }
        List<TomcatGlobalRequestProcessorInfo> globalRequestProcessorInfoList = new ArrayList<>();
        TomcatGlobalRequestProcessorInfo globalRequestProcessorInfo;
        for (ObjectName processor : processors) {
            globalRequestProcessorInfo = new TomcatGlobalRequestProcessorInfo();

            globalRequestProcessorInfo.setRequestCount(JmxUtil.getMbeanIntegerVal(processor, "requestCount"));
            globalRequestProcessorInfo.setProcessingTime(JmxUtil.getMbeanLongVal(processor, "processingTime"));
            globalRequestProcessorInfo.setMaxTime(JmxUtil.getMbeanLongVal(processor, "maxTime"));
            globalRequestProcessorInfo.setErrorCount(JmxUtil.getMbeanIntegerVal(processor, "errorCount"));
            globalRequestProcessorInfo.setBytesSent(JmxUtil.getMbeanLongVal(processor, "bytesSent"));
            globalRequestProcessorInfo.setBytesReceived(JmxUtil.getMbeanLongVal(processor, "bytesReceived"));

            globalRequestProcessorInfoList.add(globalRequestProcessorInfo);
        }
        return globalRequestProcessorInfoList;
    }


    /**
     * 获取 Tomcat 连接器的监控信息
     *
     * @return List<TomcatConnectorInfo>
     */
    public static List<TomcatConnectorInfo> getTomcatConnectorInfos() {
        Set<ObjectName> connectors = JmxUtil.getObjectNameSet(JmxUtil.EMBEDDED_TOMCAT_CONNECTOR);

        if (CollectionUtil.isEmpty(connectors)) {
            connectors = JmxUtil.getObjectNameSet(JmxUtil.STANDALONE_TOMCAT_CONNECTOR);
            if (CollectionUtil.isEmpty(connectors)) {
                return null;
            }
        }
        List<TomcatConnectorInfo> connectorInfoList = new ArrayList<>();
        TomcatConnectorInfo connectorInfo;
        for (ObjectName connector : connectors) {
            connectorInfo = new TomcatConnectorInfo();

            connectorInfo.setPort(JmxUtil.getMbeanIntegerVal(connector, "port"));
            connectorInfo.setUriEncoding(JmxUtil.getMbeanStrVal(connector, "URIEncoding"));
            connectorInfo.setScheme(JmxUtil.getMbeanStrVal(connector, "scheme"));

            connectorInfo.setProtocol(JmxUtil.getMbeanStrVal(connector, "protocol"));
            connectorInfo.setProtocolHandlerClassName(JmxUtil.getMbeanStrVal(connector, "protocolHandlerClassName"));

            connectorInfo.setAcceptCount(JmxUtil.getMbeanIntegerVal(connector, "acceptCount"));

            connectorInfo.setConnectionTimeout(JmxUtil.getMbeanIntegerVal(connector, "connectionTimeout"));
            connectorInfo.setMaxThreads(JmxUtil.getMbeanIntegerVal(connector, "maxThreads"));
            connectorInfo.setMinSpareThreads(JmxUtil.getMbeanIntegerVal(connector, "minSpareThreads"));

            connectorInfoList.add(connectorInfo);
        }
        return connectorInfoList;
    }


    /**
     * 获取 Tomcat 协议处理器的监控信息
     *
     * @return List<TomcatProtocolHandlerInfo>
     */
    public static List<TomcatProtocolHandlerInfo> getTomcatProtocolHandlerInfos() {
        Set<ObjectName> processors = JmxUtil.getObjectNameSet(JmxUtil.EMBEDDED_TOMCAT_PROTOCOL_HANDLER);
        if (CollectionUtil.isEmpty(processors)) {
            processors = JmxUtil.getObjectNameSet(JmxUtil.STANDALONE_TOMCAT_PROTOCOL_HANDLER);
            if (CollectionUtil.isEmpty(processors)) {
                return null;
            }
        }

        List<TomcatProtocolHandlerInfo> protocolHandlerInfoList = new ArrayList<>();
        TomcatProtocolHandlerInfo protocolHandlerInfo;

        for (ObjectName processor : processors) {
            protocolHandlerInfo = new TomcatProtocolHandlerInfo();

            protocolHandlerInfo.setMaxConnections(JmxUtil.getMbeanIntegerVal(processor, "maxConnections"));
            protocolHandlerInfo.setConnectionCount(JmxUtil.getMbeanLongVal(processor, "connectionCount"));
            protocolHandlerInfo.setAcceptCount(JmxUtil.getMbeanIntegerVal(processor, "acceptCount"));
            protocolHandlerInfo.setWaitingProcessorCount(JmxUtil.getMbeanIntegerVal(processor, "waitingProcessorCount"));
            protocolHandlerInfo.setConnectionTimeout(JmxUtil.getMbeanIntegerVal(processor, "connectionTimeout"));
            protocolHandlerInfo.setMaxThreads(JmxUtil.getMbeanIntegerVal(processor, "maxThreads"));
            protocolHandlerInfo.setMinSpareThreads(JmxUtil.getMbeanIntegerVal(processor, "minSpareThreads"));

            protocolHandlerInfoList.add(protocolHandlerInfo);
        }
        return protocolHandlerInfoList;
    }

    /**
     * 获取 Tomcat 的线程池的监控信息
     *
     * @return List<TomcatThreadPoolInfo>
     */
    public static List<TomcatThreadPoolInfo> getTomcatThreadPoolInfos() {
        Set<ObjectName> threadPools = JmxUtil.getObjectNameSet(JmxUtil.EMBEDDED_TOMCAT_THREAD_POOL);
        if (CollectionUtil.isEmpty(threadPools)) {
            threadPools = JmxUtil.getObjectNameSet(JmxUtil.STANDALONE_TOMCAT_THREAD_POOL);
            if (CollectionUtil.isEmpty(threadPools)) {
                return null;
            }
        }

        List<TomcatThreadPoolInfo> threadPoolInfoList = new ArrayList<>();
        TomcatThreadPoolInfo threadPoolInfo;
        for (ObjectName threadPool : threadPools) {
            threadPoolInfo = new TomcatThreadPoolInfo();

            threadPoolInfo.setPort(JmxUtil.getMbeanIntegerVal(threadPool, "port"));
            threadPoolInfo.setDomain(JmxUtil.getMbeanStrVal(threadPool, "domain"));
            threadPoolInfo.setName(JmxUtil.getMbeanStrVal(threadPool, "name"));
            threadPoolInfo.setMaxConnections(JmxUtil.getMbeanIntegerVal(threadPool, "maxConnections"));
            threadPoolInfo.setConnectionCount(JmxUtil.getMbeanLongVal(threadPool, "connectionCount"));
            threadPoolInfo.setAcceptCount(JmxUtil.getMbeanIntegerVal(threadPool, "acceptCount"));
            threadPoolInfo.setConnectionTimeout(JmxUtil.getMbeanIntegerVal(threadPool, "connectionTimeout"));
            // 最大线程数
            threadPoolInfo.setMaxThreads(JmxUtil.getMbeanIntegerVal(threadPool, "maxThreads"));
            threadPoolInfo.setMinSpareThreads(JmxUtil.getMbeanIntegerVal(threadPool, "minSpareThreads"));
            // 当前线程数：
            threadPoolInfo.setCurrentThreadCount(JmxUtil.getMbeanIntegerVal(threadPool, "currentThreadCount"));
            // 繁忙线程数
            threadPoolInfo.setCurrentThreadsBusy(JmxUtil.getMbeanIntegerVal(threadPool, "currentThreadsBusy"));
            threadPoolInfo.setMaxKeepAliveRequests(JmxUtil.getMbeanIntegerVal(threadPool, "maxKeepAliveRequests"));
            threadPoolInfo.setKeepAliveCount(JmxUtil.getMbeanIntegerVal(threadPool, "keepAliveCount"));
            threadPoolInfo.setKeepAliveTimeout(JmxUtil.getMbeanIntegerVal(threadPool, "keepAliveTimeout"));

            threadPoolInfo.setSelectorTimeout(JmxUtil.getMbeanLongVal(threadPool, "selectorTimeout"));

            threadPoolInfo.setTcpNoDelay(JmxUtil.getMbeanBooleanVal(threadPool, "tcpNoDelay"));

            threadPoolInfoList.add(threadPoolInfo);
        }
        return threadPoolInfoList;
    }

    /**
     * 获取 Tomcat 中 DispatcherServletInfo 的监控
     *
     * @return List<TomcatDispatcherServletInfo>
     */
    public static List<TomcatDispatcherServletInfo> getTomcatDispatcherServletInfos() {
        Set<ObjectName> servlets = JmxUtil.getObjectNameSet(JmxUtil.EMBEDDED_TOMCAT_SERVLET);
        if (CollectionUtil.isEmpty(servlets)) {
            servlets = JmxUtil.getObjectNameSet(JmxUtil.STANDALONE_TOMCAT_SERVLET);
            if (CollectionUtil.isEmpty(servlets)) {
                return null;
            }
        }
        List<TomcatDispatcherServletInfo> dispatcherServletInfoList = new ArrayList<>();
        TomcatDispatcherServletInfo dispatcherServletInfo;
        for (ObjectName servlet : servlets) {
            dispatcherServletInfo = new TomcatDispatcherServletInfo();

            dispatcherServletInfo.setServletClass(JmxUtil.getMbeanStrVal(servlet, "servletClass"));
            dispatcherServletInfo.setSingleThreadModel(JmxUtil.getMbeanBooleanVal(servlet, "singleThreadModel"));
            dispatcherServletInfo.setAsyncSupported(JmxUtil.getMbeanBooleanVal(servlet, "asyncSupported"));
            dispatcherServletInfo.setRequestCount(JmxUtil.getMbeanIntegerVal(servlet, "requestCount"));
            dispatcherServletInfo.setErrorCount(JmxUtil.getMbeanIntegerVal(servlet, "errorCount"));
            dispatcherServletInfo.setProcessingTime(JmxUtil.getMbeanLongVal(servlet, "processingTime"));
            dispatcherServletInfo.setMinTime(JmxUtil.getMbeanLongVal(servlet, "minTime"));
            dispatcherServletInfo.setMaxTime(JmxUtil.getMbeanLongVal(servlet, "maxTime"));
            dispatcherServletInfo.setMaxInstances(JmxUtil.getMbeanIntegerVal(servlet, "maxInstances"));

            dispatcherServletInfoList.add(dispatcherServletInfo);
        }
        return dispatcherServletInfoList;
    }


    /**
     * 获取 Tomcat 字符串缓存池监控信息
     *
     * @return List<TomcatStringCacheInfo>
     */
    public static List<TomcatStringCacheInfo> getTomcatStringCacheInfos() {
        Set<ObjectName> stringCaches = JmxUtil.getObjectNameSet(JmxUtil.EMBEDDED_TOMCAT_STRING_CACHE);
        if (CollectionUtil.isEmpty(stringCaches)) {
            stringCaches = JmxUtil.getObjectNameSet(JmxUtil.STANDALONE_TOMCAT_STRING_CACHE);
            if (CollectionUtil.isEmpty(stringCaches)) {
                return null;
            }
        }

        List<TomcatStringCacheInfo> stringCacheInfoList = new ArrayList<>();
        TomcatStringCacheInfo stringCacheInfo;

        for (ObjectName stringCache : stringCaches) {
            stringCacheInfo = new TomcatStringCacheInfo();

            stringCacheInfo.setAccessCount(JmxUtil.getMbeanIntegerVal(stringCache, "accessCount"));

            stringCacheInfo.setByteEnabled(JmxUtil.getMbeanBooleanVal(stringCache, "byteEnabled"));
            stringCacheInfo.setCharEnabled(JmxUtil.getMbeanBooleanVal(stringCache, "charEnabled"));

            stringCacheInfo.setCacheSize(JmxUtil.getMbeanIntegerVal(stringCache, "cacheSize"));
            stringCacheInfo.setHitCount(JmxUtil.getMbeanIntegerVal(stringCache, "hitCount"));
            stringCacheInfo.setTrainThreshold(JmxUtil.getMbeanIntegerVal(stringCache, "trainThreshold"));

            stringCacheInfoList.add(stringCacheInfo);
        }
        return stringCacheInfoList;
    }

}
